iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
AI Engineering

AI Reliability Lab:30 天用 Python 把「AI 好像很準」變成可以量的工程指標系列 第 6

#Day 6|AI 回答得越多,真的越好嗎?第一次做 Risk-Coverage Curve

  • 分享至 

  • xImage
  •  

昨天做完 Abstention Test 之後,我開始碰到一個很現實的問題。

Day 5 的邏輯很直覺:

不知道的時候,不要亂答。

但如果把這句話推到極端,也會出現另一個問題。

假設一個 AI 為了避免犯錯,十題只回答一題,其他九題全部說 UNKNOWN,它的錯誤率可能真的很低。

可是這樣的系統真的有用嗎?

反過來,如果 AI 每一題都回答,Coverage 看起來很漂亮,但它可能正在把大量低把握的答案一起送出去。

所以今天我想處理的問題,不再只是:

「AI 會不會拒答?」

而是:

「當我要求 AI 回答更多問題時,我到底承擔了多少額外風險?」

這就是今天的主題:

Risk-Coverage。


從「答不答」變成一條連續的控制線

Day 5 的 Abstention 比較像是一個二元決策。

一筆案例進來,最後不是:

ANSWER

就是:

UNKNOWN

但在實際系統裡,我不一定只能用一條固定規則。

如果每一筆答案都有一個 confidence score,那我就可以設定 threshold。

例如:

confidence >= 0.9

才允許回答。

threshold 很高時,系統只回答自己最有把握的案例。

threshold 降低之後,就會開始接受更多案例。

這時候就出現兩個很重要的量:

Coverage

以及

Risk


Coverage 是什麼?

Coverage 可以先理解成:

系統願意處理、願意回答的案例比例。

假設總共有 10 題。

如果 threshold 設得很高,只留下 3 題:

Coverage = 3 / 10 = 30%

如果 threshold 降低,最後 10 題全部都回答:

Coverage = 10 / 10 = 100%

所以 Coverage 越高,代表系統願意處理的範圍越大。

在使用體驗上,這通常是好事。

因為沒有人希望 AI 每次都只回:

UNKNOWN

但是 Coverage 高,本身不代表可靠。

所以還需要第二個指標。


Risk 是什麼?

今天先把 Risk 定義成:

在「已經選擇回答」的案例裡,錯誤答案佔多少。

公式可以寫成:

Risk = Errors among selected cases / Selected cases

假設 AI 選擇回答 8 題,其中錯 2 題:

Risk = 2 / 8 = 25%

注意這個 denominator 很重要。

Risk 並不是:

總錯誤數 / 全部資料

而是:

總錯誤數 / 系統真的選擇回答的資料

因為今天真正想知道的是:

當系統決定「這題我敢回答」之後,它有多常答錯?


今天先用 Synthetic Demo 驗證演算法

這裡要先把資料來源講清楚。

Day 6 的 confidence 並不是任何真實 LLM 提供的 confidence。

我今天使用的是 Synthetic Demo Data

也就是我刻意建立一組:

case_id
confidence
correct

資料,單純用來驗證 Risk-Coverage evaluator 的行為。

confidence 只是我設計的 synthetic score。

它目前不能解讀成:

「模型真的有 98% 的機率答對。」

今天只是先假設:

score 越高,系統越優先保留這筆答案。

至於這個 confidence 本身到底可不可信,會留到下一天再處理。


Threshold 越高,Coverage 越低

我今天的 Demo 一共有 10 筆案例。

Confidence 從高到低分別是:

0.98
0.93
0.88
0.82
0.76
0.69
0.61
0.54
0.43
0.31

程式會直接把資料中實際存在的 confidence values 當作 thresholds。

也就是說,不是自己硬切:

0.9
0.8
0.7
...

而是直接觀察:

如果 threshold 剛好落在每一個 observed confidence 上,系統會得到什麼 Coverage 與 Risk?

實際結果如下:

Threshold Coverage Risk
0.98 10% 0%
0.93 20% 0%
0.88 30% 0%
0.82 40% 25%
0.76 50% 20%
0.69 60% 約 17%
0.61 70% 約 29%
0.54 80% 25%
0.43 90% 約 33%
0.31 100% 40%

【截圖位置 1】Day 6 Risk-Coverage 實際輸出
建議截 Threshold / Coverage / Risk 的完整結果。


第一個發現:最低 Risk 不一定最好

如果只看表格最上面:

Threshold = 0.98
Coverage = 10%
Risk = 0%

這看起來非常漂亮。

Risk 是 0%。

但是它只回答了 10% 的案例。

換句話說:

10 題裡只處理 1 題。

如果這是一個客服系統,這種「零風險」幾乎沒有實際價值。

它不是因為真的解決了風險問題,而是因為它幾乎沒有在工作。

這讓我第一次很清楚地看到:

低 Risk 本身不是目標。

真正需要考慮的是:

在可接受的 Risk 下,可以拿到多少 Coverage?

也就是 Reliability 不再是一個單一分數,而開始變成 trade-off。


第二個發現:Risk 不一定隨 Coverage 單調增加

這次結果裡還有一個我原本很容易忽略的地方。

例如:

Coverage 40% → Risk 25%
Coverage 50% → Risk 20%
Coverage 60% → Risk 約 17%

Coverage 增加了,Risk 居然反而下降。

如果直覺上認為:

回答越多 → 一定越危險

就會覺得這結果怪怪的。

但仔細看 Risk 的定義,其實很合理。

Risk 是:

累積錯誤數 / 已選案例數

假設在 Coverage 40% 時:

4 題裡錯 1 題
Risk = 1 / 4 = 25%

接著新增的第 5 題是正確答案:

5 題裡仍然只錯 1 題
Risk = 1 / 5 = 20%

再增加一題正確答案:

6 題裡仍然只錯 1 題
Risk = 1 / 6 ≈ 16.7%

所以 Risk-Coverage Curve 並不保證是一條漂亮的單調曲線。

它會受到:

每一個新加入案例到底是對還是錯

影響。

這個現象其實很重要。

因為它提醒我:

不能只看一兩個 threshold,就直接說某個 score 很可靠。

真正有價值的是觀察整條 selection behavior


Risk-Coverage 到底在幫我決定什麼?

做到這裡,我開始覺得 Risk-Coverage 不只是「多算一個 metric」。

它其實比較像一個部署決策工具。

假設今天有兩種場景。

第一種是一般 FAQ。

可能我願意接受:

Risk <= 10%

換取比較高的 Coverage。

但如果今天是在處理一個高風險任務,我可能希望:

Risk <= 1%

就算 Coverage 比較低也沒關係。

所以系統真正的問題,不是:

哪一個 threshold 是最好的?

而是:

在我的任務裡,我願意用多少 Risk 換多少 Coverage?

這個答案不應該由 evaluator 自己決定。

Evaluator 的責任是把 trade-off 算出來。

真正的 threshold policy,應該取決於:

  • 任務風險
  • 錯誤成本
  • 是否有人類覆核
  • 系統用途
  • 可以接受多少拒答

這也是我目前不想隨便在 Quality Gate 裡寫一個固定 threshold 的原因。


程式怎麼算?

Day 6 的邏輯其實沒有很複雜。

先取出每一筆:

confidence
correct

接著把 observed confidence values 由高到低排序。

對每一個 threshold:

selected = confidence >= threshold

然後計算:

Coverage
= selected_count / total_count

以及:

Risk
= selected_errors / selected_count

最後每一個 threshold 都形成一個 operating point。

概念上大概像:

for threshold in thresholds:
    selected = [
        record
        for record in records
        if record.confidence >= threshold
    ]

    coverage = len(selected) / len(records)

    errors = sum(
        not record.is_correct
        for record in selected
    )

    risk = errors / len(selected)

現在的 Foundation v1.1 會把結果整理成 structured metric。

每一個 point 都會留下:

threshold
coverage
risk
selected
errors

這樣未來真的要畫 Risk-Coverage Curve 時,就不用重新算一次。


為什麼目前沒有直接畫圖?

既然名字都叫:

Risk-Coverage Curve

理論上今天好像應該直接畫一條圖。

但我這次刻意先沒有加 matplotlib。

因為目前這個專案還在建立 evaluator 的底層。

如果今天為了文章好看,先把資料計算、plotting、輸出邏輯全部混在一起,之後反而比較難整理。

所以現在我先讓 metric 產生 structured result。

例如:

{
  "threshold": 0.82,
  "coverage": 0.4,
  "risk": 0.25,
  "selected": 4,
  "errors": 1
}

之後不管是:

  • matplotlib
  • Streamlit
  • dashboard
  • case viewer

都可以直接吃 artifact 裡的結果。

我現在希望慢慢維持一個原則:

Metric 負責計算,Visualization 負責顯示。


Day 5 與 Day 6 的差別

做到今天,我覺得 Day 5 和 Day 6 看起來很像,但其實在問不同的問題。

Day 5 的問題是:

系統知不知道什麼時候應該拒答?

所以我看的是:

  • Correct Abstention
  • Unsafe Answer
  • Over-refusal
  • Coverage
  • Selective Accuracy

Day 6 則更像:

如果我改變接受答案的 threshold,整個系統的 Risk 與 Coverage 會怎麼變?

Day 5 比較像在評估一個固定 policy。

Day 6 則開始評估:

不同 policy operating points。

這也讓 Reliability Lab 從「評分 AI」慢慢走向:

幫系統做部署決策。


目前的結果不能代表真實模型

這裡還是要再強調一次。

今天表格裡的:

0.98
0.93
0.88
...

全部都是 synthetic confidence。

它們是為了測試 evaluator 而設計的數字。

所以目前我能說的是:

Risk-Coverage evaluator 能根據 confidence ranking,正確計算不同 threshold 下的 Coverage 與 Risk。

但我還不能說:

某個真實模型在 threshold 0.82 時,Risk 是 25%。

更不能說:

AI 的 0.82 confidence 真的代表 82% 機率正確。

這兩件事情目前都還沒有做 real experiment。


今天最大的問題,其實藏在 confidence 裡

做到這裡,我原本應該很開心。

因為現在已經可以做:

confidence threshold
↓
selected answers
↓
Coverage
↓
Risk

看起來好像已經有一套不錯的 selection policy。

但是我突然發現整套方法其實都建立在一個還沒有回答的假設上:

那個 confidence 到底可信不可信?

假設一個系統每次答錯,都還是給自己:

confidence = 0.99

那 Risk-Coverage evaluator 就算算得再準,也只是在使用一個很差的 score 排序。

甚至更進一步:

如果 AI 說:

我有 90% 把握。

這句話到底代表什麼?

真的表示:

類似情況下大約 90% 會答對?

還是只是模型隨口產生了一個看起來很有自信的數字?

這就是 Day 6 留下來最大的問題。


Day 6 結論

Day 5 做完 Abstention 時,我原本把重點放在:

AI 要學會說不知道。

但 Day 6 讓問題變得更完整。

一個真正實用的系統,不可能只追求最低錯誤率。

因為如果幾乎所有案例都拒答,Risk 再低也沒有意義。

真正需要處理的是:

在可以接受的 Risk 下,我能保留多少 Coverage?

今天的 Synthetic Demo 裡:

Coverage 10% → Risk 0%
Coverage 40% → Risk 25%
Coverage 60% → Risk 約 17%
Coverage 80% → Risk 25%
Coverage 100% → Risk 40%

也讓我看到 Risk-Coverage 並不是一條必然單調的線,而是會隨著被納入的案例正確與否產生變化。

目前 Reliability Lab 已經開始把:

Accuracy
Consistency
Format Compliance
Abstention
Coverage
Risk
Quality Gate

接成同一條工程思路。

但今天最後反而冒出一個更根本的問題:

如果我要靠 confidence 決定哪些答案值得相信,那我是不是應該先驗證 confidence 本身?

所以 Day 7,我要開始做:

Calibration。

下一步不只是問:

AI 有多有自信?

而是問:

AI 說自己有 90% 把握時,它真的大約有 90% 會答對嗎?


上一篇
Day 5|「我不知道」可能是 AI 最可靠的一句話:第一次把拒答變成工程指標
下一篇
Day 7|AI 說自己有 95% 把握,我真的該信嗎?第一次把 Confidence 拿去校準
系列文
AI Reliability Lab:30 天用 Python 把「AI 好像很準」變成可以量的工程指標10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言